package com.jrx.anytxn.param.service.system.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.i18n.context.BaseContextHandler;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.dto.system.CodeTableReq;
import com.jrx.anytxn.param.dto.system.CodeTableRes;
import com.jrx.anytxn.param.dto.system.CodeTableTypeReq;
import com.jrx.anytxn.param.dto.system.CodeTableTypeRes;
import com.jrx.anytxn.param.entity.I18nCore;
import com.jrx.anytxn.param.entity.PrCodeTable;
import com.jrx.anytxn.param.entity.PrCodeTableType;
import com.jrx.anytxn.param.mapper.ext.ExtI18nCoreMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrCodeTableMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrCodeTableTypeMapper;
import com.jrx.anytxn.param.service.product.impl.AmortMethodServiceImpl;
import com.jrx.anytxn.param.service.system.ICodeTableTypeService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @author by yf
 * @Classname CodeTableTypeServiceImpl
 * @Description 代码表类型
 * @Date 2019/7/11 0011 下午 14:57
 */
@Service
@CacheConfig(cacheNames = "CODE_TABLE")
public class CodeTableTypeServiceImpl implements ICodeTableTypeService {

    private static final Logger logger = LoggerFactory.getLogger(AmortMethodServiceImpl.class);

    @Resource
    private ExtPrCodeTableTypeMapper extPrCodeTableTypeMapper;
    @Resource
    private ExtPrCodeTableMapper extPrCodeTableMapper;
    @Autowired
    private ISegmentService segmentService;
    @Resource
    private ExtI18nCoreMapper extI18nCoreMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public TxnPage<CodeTableTypeRes> findAllPageByTenId(Integer pageNum, Integer pageSize, String tenantId,String typeId,String typeName,String typeDescription) throws TxnException {
        Page<CodeTableTypeRes> page = PageHelper.startPage(pageNum, pageSize,Constant.ORDER_BY_CODE_SORT);
        List<PrCodeTableType> prCodeTableTypeList = extPrCodeTableTypeMapper.selectByTenId(tenantId,typeId,typeName,typeDescription);
        if (prCodeTableTypeList.isEmpty()) {
            logger.error("查询列表为空");
            throw new TxnException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg());
        }
        List<CodeTableTypeRes> res = BeanMapping.copyList(prCodeTableTypeList, CodeTableTypeRes.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CodeTableTypeRes addCodeTable(CodeTableTypeReq codeTableTypeReq,String updateBy) throws TxnException {
        PrCodeTableType prCodeTableType = BeanMapping.copy(codeTableTypeReq, PrCodeTableType.class);
        /*根据代码类型ID查看是否已存在*/
        PrCodeTableType codeType = extPrCodeTableTypeMapper.selectByTypeIdAndTenId(prCodeTableType.getTypeId(), codeTableTypeReq.getTenantId());
        if (codeType != null) {
            logger.error("此代码类型已存在");
            throw new TxnException(TxnRespCode.DATA_EXISTS.getCode(), TxnRespCode.DATA_EXISTS.getMsg(ErrorMsgConstant.CODE_TYPE_EXISTS));
        }
        /*查看此还款顺序下的账户类型是否相同*/
        List<CodeTableReq> codeTableResList = codeTableTypeReq.getCodeList();
        Set<PrCodeTable> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getCodeId().equalsIgnoreCase(o2.getCodeId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        List<PrCodeTable> codeTables = BeanMapping.copyList(codeTableResList, PrCodeTable.class);
        set.addAll(codeTables);
        if (new ArrayList<>(set).size() != codeTableResList.size()) {
            throw new TxnException(ErrorMsgConstant.NO_CODE_REPETITION);
        }
        /*增加代码类型信息*/
        prCodeTableType.setTenantId(codeTableTypeReq.getTenantId());
        prCodeTableType.setUpdateBy(updateBy);
        prCodeTableType.setRecordVersionNumber(Constant.VERSION_NUMBER);
        extPrCodeTableTypeMapper.insertSelective(prCodeTableType);
        /*增加代码信息*/
        for (PrCodeTable pr : codeTables) {
            try {
                pr.setId(segmentService.getId(Constant.PR_CODE_TABLE));
            } catch (SegmentException e) {
                logger.error("主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            pr.setTenantId(codeTableTypeReq.getTenantId());
            pr.setTypeId(prCodeTableType.getTypeId());
            pr.setUpdateBy(updateBy);
            pr.setRecordVersionNumber(Constant.VERSION_NUMBER);
            extPrCodeTableMapper.insertSelective(pr);
        }
        if (Constant.SMS_FILTER.equalsIgnoreCase(prCodeTableType.getTypeId())) {
            saveToRedis(Constant.SMS_FILTER, codeTables.stream().filter(code -> Constant.YES_FLAG.equalsIgnoreCase(code.getIsvalid())).map(PrCodeTable::getCodeId).collect(Collectors.joining(",")));
        }
        return BeanMapping.copy(prCodeTableType, CodeTableTypeRes.class);
    }

    @CacheEvict(key = "'codeTable_'+#codeTableTypeReq.tenantId+'_'+#codeTableTypeReq.typeId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CodeTableTypeRes modifyCodeTable(CodeTableTypeReq codeTableTypeReq,String updateBy) throws TxnException {
        PrCodeTableType prCodeTableType = BeanMapping.copy(codeTableTypeReq, PrCodeTableType.class);
        prCodeTableType.setUpdateBy(updateBy);
        /*查看此还款顺序下的账户类型是否相同*/
        List<CodeTableReq> codeTableResList = codeTableTypeReq.getCodeList();
        Set<PrCodeTable> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getCodeId().equalsIgnoreCase(o2.getCodeId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        List<PrCodeTable> codeTables = BeanMapping.copyList(codeTableResList, PrCodeTable.class);
        set.addAll(codeTables);
        if (new ArrayList<>(set).size() != codeTableResList.size()) {
            throw new TxnException(ErrorMsgConstant.NO_CODE_REPETITION);
        }
        /*修改代码类型表信息*/
        extPrCodeTableTypeMapper.updateByTypeIdAndTenId(prCodeTableType);
        /*修改代码表信息(先删除后增加)*/
        extPrCodeTableMapper.deleteByTypeIdAndTenId(codeTableTypeReq.getTypeId(), codeTableTypeReq.getTenantId());
        for (PrCodeTable pr : codeTables) {
            try {
                pr.setId(segmentService.getId(Constant.PR_CODE_TABLE));
            } catch (SegmentException e) {
                logger.error("主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            pr.setTenantId(codeTableTypeReq.getTenantId());
            pr.setTypeId(prCodeTableType.getTypeId());
            pr.setUpdateBy(updateBy);
            pr.setRecordVersionNumber(Constant.VERSION_NUMBER);
            extPrCodeTableMapper.insertSelective(pr);
        }
        if (Constant.SMS_FILTER.equalsIgnoreCase(prCodeTableType.getTypeId())) {
            saveToRedis(Constant.SMS_FILTER, codeTables.stream().filter(code -> Constant.YES_FLAG.equalsIgnoreCase(code.getIsvalid())).map(PrCodeTable::getCodeId).collect(Collectors.joining(",")));
        }
        return BeanMapping.copy(prCodeTableType, CodeTableTypeRes.class);
    }

    /**
     * 保存到redis
     * @param key
     * @param value
     */
    private void saveToRedis(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    @Override
    public CodeTableTypeRes findByTypeIdAndTenId(String typeId, String tenantId) throws TxnException {
        if (StringUtils.isBlank(typeId) || StringUtils.isBlank(tenantId)) {
            logger.error("代码类型ID为空");
            throw new TxnException(TxnRespCode.NOT_EMPTY.getCode(), TxnRespCode.NOT_EMPTY.getMsg(ErrorMsgConstant.NO_CODE_LIST_ID));
        }
        /*查询代码类型信息*/
        PrCodeTableType prCodeTableType = extPrCodeTableTypeMapper.selectByTypeIdAndTenId(typeId, tenantId);
        /*查询代码信息*/
        List<PrCodeTable> prCodeTableList = extPrCodeTableMapper.selectAllByTypeIdAndTenId(typeId, tenantId);
       /* //在I18nCode表中获取某国际化语言的所有该类型code值
        String languageType = (String) BaseContextHandler.get("languageType");
        List<I18nCore> i18nCoreList=extI18nCoreMapper.selectByTenIdAndTypeIdAndTabNameAndLangType(tenantId,typeId,"pr_code_table",languageType);
        for (PrCodeTable prCodeTable:prCodeTableList) {
            prCodeTable.setCodeName(i18nCoreList.stream().filter(i18nCore -> i18nCore.getCodeId().equals(prCodeTable.getCodeId())).findAny().orElse(null).getI18nValue());
            prCodeTable.setCodeDescription(i18nCoreList.stream().filter(i18nCore -> i18nCore.getCodeId().equals(prCodeTable.getCodeId())).findAny().orElse(null).getI18nDesc());
        }*/
        CodeTableTypeRes codeTableTypeRes = BeanMapping.copy(prCodeTableType, CodeTableTypeRes.class);
        codeTableTypeRes.setCodeList(BeanMapping.copyList(prCodeTableList, CodeTableRes.class));
        return codeTableTypeRes;
    }

    @CacheEvict(key = "'codeTable_'+#tenantId+'_'+#typeId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeByTypeIdAndTenId(String typeId, String tenantId) throws TxnException {
        if (StringUtils.isBlank(typeId) || StringUtils.isBlank(tenantId)) {
            logger.error("代码类型ID为空");
            throw new TxnException(TxnRespCode.NOT_EMPTY.getCode(), TxnRespCode.NOT_EMPTY.getMsg(ErrorMsgConstant.NO_CODE_LIST_ID));
        }
        /*删除代码类型信息*/
        extPrCodeTableTypeMapper.deleteByTypeIdAndTenId(typeId, tenantId);
        /*删除代码信息*/
        int a = extPrCodeTableMapper.deleteByTypeIdAndTenId(typeId, tenantId);
        if (Constant.SMS_FILTER.equalsIgnoreCase(typeId)) {
            stringRedisTemplate.delete(typeId);
        }
        return a > 0;
    }
}
